CONTENTS | INDEX | PREV | NEXT
 GetHead
 GetTail
 GetSucc
 GetPred

 NAME
  GetHead     -   get first element in EXEC list
  GetTail     -   get last element in EXEC list
  GetSucc     -   get next element after some element (node)
  GetPred     -   get previous element before some element (node)

 SYNOPSIS
  struct Node *node = GetHead(list);
  struct Node *node = GetTail(list);
  struct Node *node = GetSucc(oldNode);
  struct Node *node = GetPred(oldNode);

  const struct Node *oldNode;
  const struct List *list;

 FUNCTION
  These functions allow scannig of EXEC style lists (which are also
  useful for many programs having nothing to do with EXEC)

  GetHead() returns the first node in a list or NULL if the list is
        empty

  GetTail() returns the last node in a list or NULL if the list is
        empty

  GetSucc() returns the next node in a list (given some intermediate
        node) or NULL when we reach the end of the list

  GetPred() returns the previous node in a list before some intermediate
        node or NULL when we reach the beginning of the list

 NOTE
  These are DICE functions and do not exist outside of DICE, though
  easily written.

 EXAMPLE
  /*
   *  Stupid symbol create/delete/list program.  Note that for a real
   *  symbol table you want to use hash tables.
   */

  #include <lists.h>  /*  non-standard header file    */
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>

  typedef struct List List;
  typedef struct Node Node;

  List    SymList;

  void AddSymbol(char *);
  void DelSymbol(char *);
  Node *FindSymbol(char *);

  main()
  {
      char buf[256];
      char symBuf[256];
      short notDone = 1;

      NewList(&SymList);

      puts("(return for help)");

      while (notDone) {
      printf("Enter Command: ");
      fflush(stdout);
      if (gets(buf) == NULL)
          break;
      switch(buf[0]) {
      case 'a':
          if (sscanf(buf + 1, "%s", symBuf) == 1)
          AddSymbol(symBuf);
          break;
      case 'd':
          if (sscanf(buf + 1, "%s", symBuf) == 1)
          DelSymbol(symBuf);
          break;
      case 'l':
          {
          Node *node;
          for (node = GetHead(&SymList); node; node = GetSucc(node))
              puts(node->ln_Name);
          }
          break;
      case 'q':
          notDone = 0;
          break;
      default:
          puts("<return>      -help   ");
          puts("a name        -add symbol");
          puts("d name        -delete symbol");
          puts("l             -list symbols");
          puts("q             -quit");
          break;
      }
      }
      puts("bye!");
      return(0);
  }

  void
  AddSymbol(name)
  char *name;
  {
      Node *node;
      if (FindSymbol(name)) {
      puts("already exists!");
      exit(1);
      }
      if (node = malloc(sizeof(Node))) {
      AddTail(&SymList, node);
      node->ln_Name = strdup(name);   /* bad code, not checking */
                      /* for error result!      */
      }
  }

  void
  DelSymbol(name)
  char *name;
  {
      Node *node;

      if (node = FindSymbol(name)) {
      Remove(node);           /*  take out of list    */
      free(node->ln_Name);    /*  free name           */
      free(node);             /*  free node last      */
      puts("ok");
      } else {
      puts("Couldn't find it!");
      }
  }

  Node *
  FindSymbol(name)
  char *name;
  {
      Node *node;
      for (node = GetHead(&SymList); node; node = GetSucc(node)) {
      if (strcmp(node->ln_Name, name) == 0)
          return(node);
      }
      return(NULL);
  }


 INPUTS
  struct List *list;  list to get head or tail node from

  struct Node *oldNode;   node from which to get relative successor or
              predecessor from

 RESULTS
  struct Node *node;  returned node or NULL

 SEE ALSO